package pinboard.dataLayer.potocol.op;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import pinboard.dataLayer.ByteArrayConvert;
import pinboard.dataLayer.RefBag;

public class FixedSizeLoader {
    public synchronized byte[][] fill(byte[] input) {
        List<byte[]> result = new ArrayList<>();

        RefBag<Integer> offset = new RefBag<>();
        offset.data = 0;

        byte[] onceRead = null;
        do {
            onceRead = fillUnit(input, offset);
            if (onceRead != null) {
                result.add(onceRead);
            }
        } while (onceRead != null);

        byte[][] resultArrays = new byte[result.size()][];
        result.toArray(resultArrays);
        return resultArrays;
    }

    Integer unitLength = null;//待读取的包长度

    ByteArrayOutputStream cache = new ByteArrayOutputStream();

    //足以填满fullLength，则返回全部缓冲的byte，并且清零ByteArrayOutputStream。否则返回null。
    private synchronized byte[] fillUnit(byte[] input, RefBag<Integer> offset, int fullLength) {
        int canReadLength = input.length - offset.data;
        int need = fullLength - cache.size();
        if (need <= canReadLength) {//足够填充
            cache.write(input, offset.data, need);
            offset.data = offset.data + need;
            byte[] result = cache.toByteArray();
            cache.reset();
            return result;
        } else {//不足填充
            cache.write(input, offset.data, canReadLength);
            offset.data = offset.data + canReadLength;
            return null;
        }
    }


    private synchronized byte[] fillUnit(byte[] input, RefBag<Integer> offset) {
        if (unitLength == null) {//说明之前的存量数据不足4个byte，得不到一个int32作为包待读取长度
            byte[] fillReturn = fillUnit(input, offset, 4);
            if (fillReturn != null) {
                unitLength = ByteArrayConvert.bytes2Int(fillReturn);
            }
        }
        if (unitLength != null) {
            byte[] fillReturn = fillUnit(input, offset, unitLength);
            if (fillReturn != null) {
                unitLength = null;//满了一个包，要清空待读取长度
            }
            return fillReturn;
        }
        return null;
    }
}
